package com.ktgj.pay.phoneSound;

import com.ktgj.pay.utils.LogLevel;
import com.ktgj.pay.utils.SslConnection;
import com.ktgj.pay.utils.Toolkit;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
import java.util.Timer;


public class TransactionClient {
	private static Timer timer = new Timer();
	private static boolean started = false;
	
	public TransactionClient(String url) {
		this.url = url;
	}

	private String merchantNo="";
	private String terminalNo="";
	private String merchantPwd="";
	private String url="";
	private int timeout = 120000;
	private String ServerCert;
	private int contentLength=6;

	public void setMerchantNo(String merchantNo) {
		this.merchantNo = merchantNo;
	}

	public String getMerchantNo() {
		return merchantNo;
	}

	public void setTerminalNo(String terminalNo) {
		this.terminalNo = terminalNo;
	}

	public void setMerchantPwd(String merchantPwd) {
		this.merchantPwd = merchantPwd;
	}

	public String getTerminalNo() {
		return terminalNo;
	}

	public String getMerchantPwd() {
		return merchantPwd;
	}

	private String getServerCert() {
		return ServerCert;
	}

	public void setServerCert(String serverCert) {
		ServerCert = serverCert;
	}
	
	/**
	 * �����̻�ϵͳ�������������Ƿ���ͨ
	 * @param acqSsn ϵͳ���ٺ�
	 * @param encryptKey ���������Կ
	 * @return
	 * @throws Exception
	 */
	public SimpleXml connectionTest(String acqSsn, String encryptKey) throws Exception{
	    SimpleXmlImpl request = new SimpleXmlImpl();
	    request.setVersion("2.1.0");
	    request.setProcCode("0800");
	    request.setAcqSsn(acqSsn);
        request.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
	    request.setMerchantNo(merchantNo);
	    request.setTerminalNo(terminalNo);
	    return sender(request, encryptKey);
    }

	/**
	 * ��ѯ�����ֻ�����ID����Ϣ�Ƿ��������֧��
	 * @param acqSsn ϵͳ���ٺ�
	 * @param accountNo ���׿���
	 * @param accountType
	 * @param mobileNo �����ֻ���
	 * @param amount ���
	 * @param currency ����
	 * @param idCardName ֤������
	 * @param idCardNo ֤����
	 * @param bankAddress
	 * @param idCardType ֤������
	 * @param beneficiaryName ������
	 * @param beneficiaryMobileNo �������ֻ���
	 * @param transData ��ҵ���ݣ���ID��
	 * @param deviceData
	 * @param deliveryAddress ��Ʒ��ַ
	 * @param ipAddress
	 * @param location
	 * @param userFlag ��֤�츶��ʶ
	 * @param idCardAddress ������ַ
	 * @param bankMobileNo ���еǼ��ֻ���
	 * @param idCardPhoto
	 * @param smsCode ������
	 * @param encryptKey ���������Կ
	 * @return
	 * @throws Exception
	 */
    public SimpleXml accountQuery(String acqSsn, String accountNo, String accountType, String mobileNo,
        String amount, String currency, String idCardName, String idCardNo, String bankAddress, String idCardType,
        String beneficiaryName, String beneficiaryMobileNo, String transData, String deviceData, String deliveryAddress, 
        String ipAddress, String location, String userFlag, String idCardAddress,  String bankMobileNo, String idCardPhoto, 
        String smsCode, String encryptKey) throws Exception
    {
        SimpleXmlImpl request = new SimpleXmlImpl();
        request.setProcCode("0100");
        request.setVersion("2.1.0");
        request.setProcessCode("300002");
        request.setAccountNo(accountNo);
        request.setAccountType(accountType);
        request.setMobileNo(mobileNo);
        request.setAmount(amount);
        request.setCurrency(currency);
        request.setTerminalNo(terminalNo);
        request.setMerchantNo(merchantNo);
        request.setAcqSsn(acqSsn);
        request.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
        request.setIDCardName(idCardName);
        request.setIDCardNo(idCardNo);
        request.setBankAddress(bankAddress);
        request.setIDCardType(idCardType);
        request.setBeneficiaryName(beneficiaryName);
        request.setBeneficiaryMobileNo(beneficiaryMobileNo);
        request.setTransData(transData);
        request.setDeviceData(deviceData);
        request.setDeliveryAddress(deliveryAddress);
        request.setIpAddress(ipAddress);
        request.setLocation(location);
        request.setUserFlag(userFlag);
        request.setIDCardAddress(idCardAddress);
        request.setBankMobileNo(bankMobileNo);
        request.setIDCardPhoto(idCardPhoto);
        request.setSMSCode(smsCode);
        return transact(request, encryptKey);
    }

    /**
     * ��ѯ����֧��״̬
     * @param acqSsn ϵͳ���ٺ�
     * @param accountNo ���׿���
     * @param accountType
     * @param mobileNo �����ֻ���
     * @param orderNo ����ϵͳ������
     * @param  �̻�������
     * @param encryptKey ���������Կ
     * @return
     * @throws Exception
     */
    public SimpleXml orderQuery(String acqSsn, String accountNo, String accountType, String mobileNo,
        String orderNo, String MerchantOrderNo, String encryptKey) throws Exception
    {
        SimpleXmlImpl request = new SimpleXmlImpl();
        request.setProcCode("0120");
        request.setVersion("2.1.0");
        request.setProcessCode("310000");
        request.setAccountNo(accountNo);
        request.setAccountType(accountType);
        request.setMobileNo(mobileNo);
        request.setTerminalNo(terminalNo);
        request.setMerchantNo(merchantNo);
        request.setAcqSsn(acqSsn);
        request.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
        request.setOrderNo(orderNo);
        request.setMerchantOrderNo(MerchantOrderNo);
        return transact(request, encryptKey);
    }

    /**
     * �¼�ʱ��������֧�������·Ǽ�ʱ���ӳ�֧��
     * @param acqSsn ϵͳ���ٺ�
     * @param accountNo ���׿���
     * @param accountType
     * @param mobileNo �����ֻ���
     * @param amount ���
     * @param currency ����
     * @param synAddress ͬ����ַ
     * @param asynAddress �첽��ַ
     * @param merchantName �̻�����
     * @param merchantOrderNo �̻�������
     * @param orderFrom ������Դ
     * @param language ��������
     * @param description ��������
     * @param remark ��ע
     * @param orderType �µ�����
     * @param idCardName ֤������
     * @param idCardNo ֤����
     * @param bankAddress
     * @param idCardType ֤������
     * @param beneficiaryName ������
     * @param beneficiaryMobileNo �������ֻ���
     * @param transData ��ҵ���ݣ���ID��
     * @param deviceData
     * @param deliveryAddress ��Ʒ��ַ
     * @param ipAddress
     * @param location
     * @param userFlag ��֤�츶��ʶ�� 02��ʾ�����û��´�ֱ�ӽ��п츶
     * @param idCardAddress ������ַ
     * @param bankMobileNo ���еǼ��ֻ���
     * @param idCardPhoto
     * @param smsCode ������
     * @param calleeNo ���к���
     * @param password ��ǿ���������ÿ���Ч��(MMYY)+CVN2
     * @param encryptKey ���������Կ
     * @return
     * @throws Exception
     */
    public SimpleXml pay(String acqSsn, String accountNo, String accountType, String mobileNo, String amount, String currency, 
        String synAddress, String asynAddress, String merchantName, String merchantOrderNo, String orderFrom, String language, 
        String description, String remark, String orderType, String idCardName, String idCardNo, String bankAddress, String idCardType,
        String beneficiaryName, String beneficiaryMobileNo, String transData, String deviceData, String deliveryAddress,
        String ipAddress, String location, String userFlag, String idCardAddress, String bankMobileNo, String idCardPhoto,
        String smsCode, String calleeNo, String password, String encryptKey) throws Exception
    {
        SimpleXmlImpl request = new SimpleXmlImpl();
        request.setProcCode("0200");
        request.setVersion("2.1.0");
        request.setProcessCode("00".equals(orderType)?"190000":"190001");
        request.setAccountNo(accountNo);
        request.setAccountType(accountType);
        request.setMobileNo(mobileNo);
        request.setAmount(amount);
        request.setCurrency(currency);
        request.setSynAddress(synAddress);
        request.setAsynAddress(asynAddress);
        request.setTerminalNo(terminalNo);
        request.setMerchantNo(merchantNo);
        request.setAcqSsn(acqSsn);
        request.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
        request.setMerchantName(merchantName);
        request.setMerchantOrderNo(merchantOrderNo);
        request.setOrderFrom(orderFrom);
        request.setLanguage(language);
        request.setDescription(description);
        request.setRemark(remark);
        request.setOrderType(orderType);
        request.setIDCardName(idCardName);
        request.setIDCardNo(idCardNo);
        request.setBankAddress(bankAddress);
        request.setIDCardType(idCardType);
        request.setBeneficiaryName(beneficiaryName);
        request.setBeneficiaryMobileNo(beneficiaryMobileNo);
        request.setTransData(transData);
        request.setDeviceData(deviceData);
        request.setDeliveryAddress(deliveryAddress);
        request.setIpAddress(ipAddress);
        request.setLocation(location);
        request.setUserFlag(userFlag);
        request.setIDCardAddress(idCardAddress);
        request.setBankMobileNo(bankMobileNo);
        request.setIDCardPhoto(idCardPhoto);
        request.setSMSCode(smsCode);
        request.setCalleeNo(calleeNo);
        request.setPassword(RSA.encryptPin(password, merchantOrderNo,  ServerCert));
        return transact(request, encryptKey);
    }

    /**
     * ����Ǽ�ʱ����֧��
     * @param acqSsn ϵͳ���ٺ�
     * @param accountNo ���׿���
     * @param accountType
     * @param mobileNo �����ֻ���
     * @param amount ���
     * @param currency ����
     * @param synAddress ͬ����ַ
     * @param asynAddress �첽��ַ
     * @param merchantName �̻�����
     * @param merchantOrderNo �̻�������
     * @param orderFrom ������Դ
     * @param language ��������
     * @param description ��������
     * @param remark ��ע
     * @param orderType �µ�����
     * @param idCardName ֤������
     * @param idCardNo ֤����
     * @param bankAddress
     * @param idCardType ֤������
     * @param beneficiaryName ������
     * @param beneficiaryMobileNo �������ֻ���
     * @param transData ��ҵ���ݣ���ID��
     * @param deviceData
     * @param deliveryAddress ��Ʒ��ַ
     * @param ipAddress
     * @param location
     * @param userFlag ��֤�츶��ʶ
     * @param idCardAddress ������ַ
     * @param bankMobileNo ���еǼ��ֻ���
     * @param idCardPhoto
     * @param smsCode ������
     * @param calleeNo ���к���
     * @param password ��ǿ���������ÿ���Ч��(MMYY)+CVN2
     * @param respCode ϵͳ������
     * @param encryptKey ���������Կ
     * @return
     * @throws Exception
     */
    public SimpleXml payOrder(String acqSsn, String accountNo, String accountType, String mobileNo, String amount, String currency, 
            String synAddress, String asynAddress, String merchantName, String merchantOrderNo, String orderFrom, String language, 
            String description, String remark, String orderType, String idCardName, String idCardNo, String bankAddress, String idCardType,
            String beneficiaryName, String beneficiaryMobileNo, String transData, String deviceData, String deliveryAddress,
            String ipAddress, String location, String userFlag, String idCardAddress, String bankMobileNo, String idCardPhoto,
            String smsCode, String calleeNo, String password, String respCode, String encryptKey) throws Exception
        {
            SimpleXmlImpl request = new SimpleXmlImpl();
            request.setProcCode("0120");
            request.setVersion("2.1.0");
            request.setProcessCode("310001");
            request.setAccountNo(accountNo);
            request.setAccountType(accountType);
            request.setMobileNo(mobileNo);
            request.setAmount(amount);
            request.setCurrency(currency);
            request.setSynAddress(synAddress);
            request.setAsynAddress(asynAddress);
            request.setTerminalNo(terminalNo);
            request.setMerchantNo(merchantNo);
            request.setAcqSsn(acqSsn);
            request.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
            request.setMerchantName(merchantName);
            request.setMerchantOrderNo(merchantOrderNo);
            request.setOrderFrom(orderFrom);
            request.setLanguage(language);
            request.setDescription(description);
            request.setRemark(remark);
            request.setOrderType(orderType);
            request.setIDCardName(idCardName);
            request.setIDCardNo(idCardNo);
            request.setBankAddress(bankAddress);
            request.setIDCardType(idCardType);
            request.setBeneficiaryName(beneficiaryName);
            request.setBeneficiaryMobileNo(beneficiaryMobileNo);
            request.setTransData(transData);
            request.setDeviceData(deviceData);
            request.setDeliveryAddress(deliveryAddress);
            request.setIpAddress(ipAddress);
            request.setLocation(location);
            request.setUserFlag(userFlag);
            request.setIDCardAddress(idCardAddress);
            request.setBankMobileNo(bankMobileNo);
            request.setIDCardPhoto(idCardPhoto);
            request.setSMSCode(smsCode);
            request.setCalleeNo(calleeNo);
            request.setRespCode(respCode);
            request.setPassword(RSA.encryptPin(password, merchantOrderNo,  ServerCert));
            return transact(request, encryptKey);
    }
    
    /**
     * �������������������������Ϊ����Ķ������Է���ȫ���˿�
     * @param acqSsn ϵͳ���ٺ�
     * @param accountNo ���׿���
     * @param accountType
     * @param mobileNo �����ֻ���
     * @param amount ���
     * @param currency ����
     * @param merchantOrderNo �̻�������
     * @param orderNo ����ϵͳ������
     * @param reference
     * @param remark ��ע
     * @param encryptKey ���������Կ
     * @return
     * @throws Exception
     */
    public SimpleXml orderQuash(String acqSsn, String accountNo, String accountType, String mobileNo, String amount, String currency,
        String merchantOrderNo, String orderNo, String reference,
        String remark, String encryptKey) throws Exception
    {
        SimpleXmlImpl request = new SimpleXmlImpl();
        request.setProcCode("0220");
        request.setVersion("2.1.0");
        request.setProcessCode("290000");
        request.setAccountNo(accountNo);
        request.setAccountType(accountType);
        request.setMobileNo(mobileNo);
        request.setAmount(amount);
        request.setCurrency(currency);
        request.setTerminalNo(terminalNo);
        request.setMerchantNo(merchantNo);
        request.setAcqSsn(acqSsn);
        request.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
        request.setMerchantOrderNo(merchantOrderNo);
        request.setOrderNo(orderNo);
        request.setReference(reference);
        request.setRemark(remark);
        return transact(request, encryptKey);
    }

    /**
     * �������������������������Ϊ����Ķ������Է���ȫ���˿�
     * @param acqSsn ϵͳ���ٺ�
     * @param accountNo ���׿���
     * @param accountType
     * @param mobileNo �����ֻ���
     * @param amount ���
     * @param currency ����
     * @param merchantOrderNo �̻�������
     * @param orderNo ����ϵͳ������
     * @param reference
     * @param remark ��ע
     * @param encryptKey ���������Կ
     * @return
     * @throws Exception
     */
    public SimpleXml orderRefund(String acqSsn, String accountNo, String accountType, String mobileNo, String amount, String currency,
        String merchantOrderNo, String orderNo, String reference,
        String remark, String encryptKey) throws Exception
    {
        SimpleXmlImpl request = new SimpleXmlImpl();
        request.setProcCode("0220");
        request.setVersion("2.1.0");
        request.setProcessCode("290001");
        request.setAccountNo(accountNo);
        request.setAccountType(accountType);
        request.setMobileNo(mobileNo);
        request.setAmount(amount);
        request.setCurrency(currency);
        request.setTerminalNo(terminalNo);
        request.setMerchantNo(merchantNo);
        request.setAcqSsn(acqSsn);
        request.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
        request.setMerchantOrderNo(merchantOrderNo);
        request.setOrderNo(orderNo);
        request.setReference(reference);
        request.setRemark(remark);
        return transact(request, encryptKey);
    }

    /**
     * �������ˣ��������ڷǵ���Ķ�������ʹ������ӿڽ����˿����ȫ��Ҳ���Բ����˿
     * @param acqSsn ϵͳ���ٺ�
     * @param accountNo ���׿���
     * @param amount ���
     * @param currency ����
     * @param idCardName ֤������
     * @param reference
     * @param remark ��ע
     * @param orderNo ����ϵͳ������
     * @param bankName ��������
     * @param encryptKey ���������Կ
     * @return
     * @throws Exception
     */
    public SimpleXml adjustApply(String acqSsn, String accountNo, String amount, String currency,
        String idCardName, String reference, String remark, String orderNo,
        String bankName, String encryptKey) throws Exception
    {
        SimpleXmlImpl request = new SimpleXmlImpl();
        request.setProcCode("0220");
        request.setVersion("2.1.0");
        request.setProcessCode("290003");
        request.setAccountNo(accountNo);
        request.setAmount(amount);
        request.setCurrency(currency);
        request.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
        request.setAcqSsn(acqSsn);
        request.setReference(reference);
        request.setRemark(remark);
        request.setTerminalNo(terminalNo);
        request.setMerchantNo(merchantNo);
        request.setOrderNo(orderNo);
        request.setIDCardName(idCardName);
        request.setBankName(bankName);
        return transact(request, encryptKey);
    }

    /**
     * ���˲�ѯ����ѯ���˵Ķ���״̬
     * @param acqSsn ϵͳ���ٺ�
     * @param accountNo ���׿���
     * @param amount ���
     * @param currency ����
     * @param idCardName ֤������
     * @param reference
     * @param remark ��ע
     * @param transDatetime ����ʱ��
     * @param bankName ��������
     * @param encryptKey ���������Կ
     * @return
     * @throws Exception
     */
    public SimpleXml adjustQuery(String acqSsn, String accountNo, String amount, String currency,
        String idCardName, String reference, String remark, String transDatetime,
        String bankName, String encryptKey) throws Exception
    {
        SimpleXmlImpl request = new SimpleXmlImpl();
        request.setProcCode("0220");
        request.setVersion("2.1.0");
        request.setProcessCode("290004");
        request.setAccountNo(accountNo);
        request.setAmount(amount);
        request.setCurrency(currency);
        request.setTransDatetime(transDatetime);
        request.setAcqSsn(acqSsn);
        request.setReference(reference);
        request.setRemark(remark);
        request.setTerminalNo(terminalNo);
        request.setMerchantNo(merchantNo);
        request.setIDCardName(idCardName);
        request.setBankName(bankName);
        return transact(request, encryptKey);
    }

    private SimpleXml transact(SimpleXml xml, String encryptKey) throws Exception
    {
    	BaseXml request = (BaseXml)xml;
        String input = ApiV2Util.getMACString(request) + " " + merchantPwd;
		MD5 md5 = new MD5();
        request.setMAC(md5.getMD5ofStr(input));

        SimpleXml result = null;
        try
        {
            result = sender(request, encryptKey);
        }
        catch (Exception ex)
        {
            Toolkit.writeLog(TransactionClient.class.getName(), "Transact", ex);
            throw ex;
        }

        String rsInput = (result == null ? "" : (ApiV2Util.getMACString(result) + " " + merchantPwd));
        if (result == null || !((BaseXml)result).getMAC().toUpperCase().equals(md5.getMD5ofStr(rsInput)))
        {
            throw new Exception("���ؽ��MACУ��ʧ��");
        }

        return result;
    }

    private SimpleXml sender(SimpleXml request, String encryptKey) throws Exception
    {
    	try {
    		
    		try {
    			if(!started){
    				started = true;
    				SystemMonitor monitor = new SystemMonitor(url, merchantNo, merchantPwd, terminalNo);
    				timer.scheduleAtFixedRate(monitor, monitor.getFirstTime(), monitor.getPeriod());
    			}
			} catch (Exception e) {
				Toolkit.writeLog(TransactionClient.class.getName(), "monitor error", e);
			}
    		
			Toolkit.writeLog(TransactionClient.class.getName(), "transact.send", url + "|" + timeout + "|" + request.toString());
			HttpURLConnection connect = null;
			if (!url.contains("https:")) {
				URL urlConnect = new URL(url);
				connect = (HttpURLConnection) urlConnect.openConnection();
			} else {
				SslConnection urlConnect = new SslConnection();
				connect = (HttpURLConnection) urlConnect.openConnection(url);
			}

			connect.setReadTimeout(timeout);
			connect.setConnectTimeout(timeout);
			connect.setRequestMethod("POST");
			connect.setDoInput(true);
			connect.setDoOutput(true);
			connect.setRequestProperty("content-type", "text/html;charset=utf-8");

			String xml = request.toString();
			Toolkit.writeLog(TransactionClient.class.getName(), "transact.xml\n", xml);
			RSAProvider rsa = new RSAProvider(Toolkit.getPropertyFromFile(Toolkit.GDYILIAN_CERT_METHOD));
			xml = rsa.sign(encryptKey, xml, this.getServerCert());
			xml = Toolkit.padLeft(xml.length() + "", contentLength) + xml;
            Toolkit.writeLog(TransactionClient.class.getName(), "transact.sign", xml);

			connect.connect();
			BufferedOutputStream out = new BufferedOutputStream(connect.getOutputStream());

			out.write(xml.getBytes("UTF-8"));
			out.flush();
			out.close();

			BufferedInputStream in = new BufferedInputStream(connect.getInputStream());
			byte[] bts = new byte[10000000];
			int totalLen = 0, len = 0;
			while ((len = in.read(bts, totalLen, 1000)) != -1) {
				totalLen += len;
			}

			String result = Toolkit.toString(new String(bts, "UTF-8"));
            Toolkit.writeLog(TransactionClient.class.getName(), "transact.result", result);
			result = rsa.verify(encryptKey, result.substring(contentLength));
            Toolkit.writeLog(TransactionClient.class.getName(), "transact.verify", result);
			return ApiV2Util.toSimpleXml(result);
		} catch (Exception e) {
			Toolkit.writeLog(LogLevel.ERROR, TransactionClient.class.getName(), e.getMessage());
			throw e;
		}
    }
    
    public SimpleXml sender(String request, String encryptKey) throws Exception
    {
    	try {
    		
			Toolkit.writeLog(TransactionClient.class.getName(), "transact.send", url + "|" + timeout + "|" + request.toString());
			HttpURLConnection connect = null;
			if (!url.contains("https:")) {
				URL urlConnect = new URL(url);
				connect = (HttpURLConnection) urlConnect.openConnection();
			} else {
				SslConnection urlConnect = new SslConnection();
				connect = (HttpURLConnection) urlConnect.openConnection(url);
			}

			connect.setReadTimeout(timeout);
			connect.setConnectTimeout(timeout);
			connect.setRequestMethod("POST");
			connect.setDoInput(true);
			connect.setDoOutput(true);
			connect.setRequestProperty("content-type", "text/html;charset=utf-8");

			String xml = request;
			RSAProvider rsa = new RSAProvider(Toolkit.getPropertyFromFile(Toolkit.GDYILIAN_CERT_METHOD));
			xml = Toolkit.padLeft(xml.length() + "", contentLength) + xml;
            Toolkit.writeLog(TransactionClient.class.getName(), "transact.sign", xml);

			connect.connect();
			BufferedOutputStream out = new BufferedOutputStream(connect.getOutputStream());

			out.write(xml.getBytes("UTF-8"));
			out.flush();
			out.close();

			BufferedInputStream in = new BufferedInputStream(connect.getInputStream());
			byte[] bts = new byte[10000000];
			int totalLen = 0, len = 0;
			while ((len = in.read(bts, totalLen, 1000)) != -1) {
				totalLen += len;
			}

			String result = Toolkit.toString(new String(bts, "UTF-8"));
            Toolkit.writeLog(TransactionClient.class.getName(), "transact.result", result);
			result = rsa.verify(encryptKey, result.substring(contentLength));
            Toolkit.writeLog(TransactionClient.class.getName(), "transact.verify", result);
			return ApiV2Util.toSimpleXml(result);
		} catch (Exception e) {
			Toolkit.writeLog(LogLevel.ERROR, TransactionClient.class.getName(), e.getMessage());
			throw e;
		}
    }
    
    /**
     * ������ȣ��ͻ�ʹ������֧����ʽ֧��ʧ�������ѡ������������ж������
     * @param acqSsn ϵͳ���ٺ�
     * @param accountNo ���׿���
     * @param mobileNo �����ֻ���
     * @param amount ���
     * @param currency ����
     * @param merchantOrderNo �̻�������
     * @param description ��������
     * @param synAddress ͬ����ַ
     * @param asynAddress �첽��ַ
     * @param merchantName �̻�����
     * @param orderFrom ������Դ
     * @param language ��������
     * @param orderType �µ�����
     * @param reference
     * @param idCardName ֤������
     * @param idCardNo ֤����
     * @param bankAddress
     * @param idCardType ֤������
     * @param beneficiaryName ������
     * @param beneficiaryMobileNo �������ֻ���
     * @param deviceData
     * @param deliveryAddress ��Ʒ��ַ
     * @param ipAddress
     * @param location
     * @param beneficiaryMobileNo ������֧������
     * @param mobileChecked
     * @param merchantAccountLevel
     * @param merchantAccountActivity
     * @param vip
     * @param transData ��ҵ���ݣ���ID��
     * @param userFlag ��֤�츶��ʶ
     * @param encryptKey ���������Կ
     * @return
     * @throws Exception
     */
    public SimpleXml rescueOrder(String acqSsn, String accountNo, String mobileNo, String amount, String currency, 
			String merchantOrderNo, String description, String synAddress,String asynAddress, String merchantName, 
			String orderFrom, String language, String orderType, String reference, String idCardName, String idCardNo,
			String bankAddress, String idCardType, String beneficiaryName, String beneficiaryMobileNo, String deviceData,
			String deliveryAddress, String ipAddress, String location, String system3rdName, boolean mobileChecked,
			int merchantAccountLevel, int merchantAccountActivity, boolean vip, String transData, String userFlag,
			String encryptKey) throws Exception {
		
		RescueXmlImpl xml = new RescueXmlImpl();
		xml.setVersion("2.3.0");
		xml.setProcCode("0200");
		xml.setProcessCode("190010");
		xml.setAcqSsn(acqSsn);
		xml.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
		xml.setMerchantNo(merchantNo);
		xml.setTerminalNo(terminalNo);
		xml.setAccountNo(accountNo);
		xml.setMobileNo(mobileNo);
		xml.setAmount(amount);
		xml.setCurrency("".equals(currency)?"CNY":currency);
		xml.setSynAddress(synAddress);
		xml.setAsynAddress(asynAddress);
		xml.setMerchantName(merchantName);
		xml.setMerchantOrderNo(merchantOrderNo);
		xml.setOrderFrom(orderFrom);
		xml.setLanguage(language);
		xml.setDescription(description);
		xml.setOrderType(orderType);
		xml.setReference(reference);
		xml.setIDCardName(idCardName);
		xml.setIDCardNo(idCardNo);
		xml.setBankAddress(bankAddress);
		xml.setIDCardType(idCardType);
		xml.setBeneficiaryName(beneficiaryName);
		xml.setBeneficiaryMobileNo(beneficiaryMobileNo);
		xml.setDeviceData(deviceData);
		xml.setDeliveryAddress(deliveryAddress);
		xml.setIpAddress(ipAddress);
		xml.setLocation(location);
		xml.setSystem3rdName(system3rdName);
		xml.setMobileChecked(mobileChecked?"1":"0");
		xml.setMerchantAccountLevel(merchantAccountLevel+"");
		xml.setMerchantAccountActivity(merchantAccountActivity+"");
		xml.setVIP(vip?"1":"0");
		xml.setTransData(transData);
		xml.setUserFlag(userFlag);

		MD5 md5 = new MD5();
		xml.setMAC(md5.getMD5ofStr(ApiV2Util.getMACString(xml) + " " + merchantPwd));
		RescueXmlImpl result = (RescueXmlImpl) transact(xml,encryptKey);
		if(result != null && !result.getMAC().equals(md5.getMD5ofStr(ApiV2Util.getMACString(result) + " " + merchantPwd))){
			throw new Exception("У��MACʧ��");
		}
		return result;
	}

    /**
     * ��ѯ�ֻ��Ƿ�����ϵͳ���û�
     * @param acqSsn ϵͳ���ٺ�
     * @param mobileNo �����ֻ���
     * @param encryptKey ���������Կ
     * @return
     * @throws Exception
     */
	public SimpleXml queryMobile(String acqSsn, String mobileNo, String encryptKey) throws Exception {
		MobileXmlImpl xml = new MobileXmlImpl();
		xml.setVersion("2.0.0");
		xml.setProcCode("0100");
		xml.setProcessCode("300010");
		xml.setAcqSsn(acqSsn);
		xml.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
		xml.setMerchantNo(merchantNo);
		xml.setTerminalNo(terminalNo);
		xml.setMobileNo(mobileNo);
		
		MD5 md5 = new MD5();
		xml.setMAC(md5.getMD5ofStr(ApiV2Util.getMACString(xml) + " " + merchantPwd));
		MobileXmlImpl result = (MobileXmlImpl) transact(xml, encryptKey);
		if(result != null && !result.getMAC().equals(md5.getMD5ofStr(ApiV2Util.getMACString(result) + " " + merchantPwd))){
			throw new Exception("У��MACʧ��");
		}
		return result;
	}
	
	/**
	 * ���Ͷ���
	 * @param acqSsn ϵͳ���ٺ�
	 * @param mobileNo �����ֻ���
	 * @param orderNo ����ϵͳ������
	 * @param encryptKey ���������Կ
	 * @return
	 * @throws Exception
	 */
	public SimpleXml sendSms(String acqSsn, String mobileNo, String orderNo, String encryptKey) throws Exception {
		WebCatXmlImpl xml = new WebCatXmlImpl();
		xml.setVersion("2.1.4");
		xml.setProcCode("0900");
		xml.setProcessCode("900002");
		xml.setAcqSsn(acqSsn);
		xml.setTransDatetime(Toolkit.yyyyMMddHHmmss(new Date()));
		xml.setMobileNo(mobileNo);
		xml.setOrderNo(orderNo);
		xml.setMerchantNo(merchantNo);
		
		MD5 md5 = new MD5();
		xml.setMAC(md5.getMD5ofStr(ApiV2Util.getMACString(xml) + " " + merchantPwd));
		WebCatXmlImpl result = (WebCatXmlImpl)transact(xml,encryptKey);
		
		if(result != null && !result.getMAC().equals(md5.getMD5ofStr(ApiV2Util.getMACString(result) + " " + merchantPwd))){
			throw new Exception("У��MACʧ��");
		}
		return result;
	}
}
